package BioProof;

use strict;
use Bio::Perl;
use Bio::Seq;
use IO::String;
use Bio::SeqIO;
use DBI;
use Error qw(:try);

sub new {
	my $class = shift;
	my $self = {};

	if($#_ != -1){
		my ($verify,$primers,$codons) = @_;
	
		$self->{seqs} = undef;
		$self->{verify} = $verify;
		$self->{primers} = $primers;
		$self->{codons} = $codons;
		$self->{primer3} = "";
		$self->{primer5} = "";
		$self->{keywords} = "";
		$self->{isFasta} = 0;
		$self->{keyerr} = 1;
		$self->{primer3err} = 1;
		$self->{primer5err} = 1;
		$self->{email} = "";
		$self->{name} = "";
		$self->{emailerr} = 0;
		$self->{codontable} = 0;
		$self->{id} = -1;
	} else {
		$self->{verify} = "";
		$self->{primers} = "";
		$self->{codons} = "";
		$self->{primer3} = "";
		$self->{primer5} = "";
		$self->{keywords} = "";
		$self->{id} = -1;
		$self->{email} = "";
		$self->{name} = "";
		$self->{codontable} = 0;
	}

	bless $self, $class;
	return $self;
} 

sub GetCodonTable {
	my $self = shift;
	return $self->{codontable};
}

sub AddCodonTable {
	my ($self, $t) = @_;
	$self->{codontable} = $t;
}

sub AddName {
	my ($self, $name) = @_;
	
	$name =~ s/^\s//;
	$name =~ s/\s$//;

	$self->{name} = $name;
}

sub AddEmail {
	my ($self, $email) = @_;
	$email =~ s/^\s//;
	$email =~ s/\s$//;

	return if($email eq "");
	
	if($email =~ m/([\w\.%+-]+@[\w\.-]+\.[a-zA-Z]{2,4})/){
		$self->{email} = $1;
		return;
	}

	$self->{emailerr} = 1;
}	

sub AddPrimers {
	my ($self, $p3, $p5) = @_;
	my $allowed = "[^AGCTNRWYMKSHBVD]";

	if($p3 =~ m/$allowed/i){
		$self->{primer3err} = 0;
	} else {
		$self->{primer3} = $p3;
	}

	if($p5 =~ m/$allowed/i){
		$self->{primer5err} = 0;
	} else {
		$self->{primer5} = $p5;
	}
}

sub AddData {
	my ($self, $seqStr) = @_;

	return if($seqStr eq "");

	try {
		my $stringfh = new IO::String($seqStr);
		my $s = $seqStr;
		my $stringfh2 = new IO::String($s);
		my $tms = Bio::SeqIO->new(-fh=>$stringfh,-format=>"fasta");
		my $seqaa = $tms->next_seq();
		my $seqs = Bio::SeqIO->new(-fh=>$stringfh2,-format=>"fasta");
		$self->{seqs} = $seqs;
		$self->{isFasta} = 1;
	} catch Bio::Root::Exception with {
		my $ex = shift;
	}
}

sub AddKeywords {
	my ($self, $key) = @_;
	
	$key =~ s/\s//g;

	unless($key =~ m/[^\w,;]/){
		my @keys = split /;/, $key; 
		my $k = "";
		foreach(@keys){
			$k .= "-k $_ ";
		}
		$self->{keywords} = $k;
	} else {
		$self->{keyerr} = 0;
	}
}

sub IsCorrect {
	my $self = shift;
	my @error = ();

	if($self->{isFasta} == 0){
		push @error , "Make sure data is in FASTA format";
	}

	if($self->{primers} eq "" && $self->{verify} eq "" && $self->{codons} eq ""){
		push @error, "Select what to verify";
	}

	if($self->{primers} eq "yes" && ($self->{primer3} eq "" || $self->{primer5} eq "")){
		my $j = 0;

		if($self->{primer3err} == 0){
			push @error , "Invalid 3' primer";
			$j = 1;
		}	

		if($self->{primer5err} == 0){
			push @error , "Invalid 5' primer";
			$j = 1;
		}	

		push @error , "Specify primer ends" if($j == 0);
	}

	if($self->{verify} eq "yes" && $self->{keywords} eq ""){
		if($self->{keyerr} == 1){
			push @error , "Specify keywords";
		} else {
			push @error, "Invalid format in keywords";
		}
	}

	if($self->{emailerr} == 1){
		push @error , "Invalid email address";
	}

	return @error;
}

sub GetEmail {
	my $self = shift;
	return $self->{email};
}

sub AddToDB{
	my $self = shift;

	my $dbh = DBI->connect("dbi:mysql:database=seqs_southwick;host=psoda2.cs.byu.edu","phylo","");

	my $SQL = "INSERT into bioproof (task,keywords,primers,codonsearch,email,name) VALUES ('PENDING','','',0,'" . $self->{email} . "','" . $self->{name} . "');";
	my $mysql = $dbh->prepare($SQL);
	$mysql->execute();
	
	my $id = $dbh->last_insert_id( undef, undef, undef, undef ) or die "Couldn't get last insert id: " . $dbh->errstr(); 


	my $dir = "tmp/job_$id";
	`mkdir $dir`;
	`chmod 777 $dir`;
	my $out = Bio::SeqIO->new(-file=>">$dir/file.fas",-format=>'fasta');

	my $seqsf = $self->{seqs};

	while(my $seq = $seqsf->next_seq){
		$out->write_seq($seq);
	}

	if($self->{verify} eq "yes"){
		$SQL = "UPDATE bioproof SET keywords='" . $self->{keywords} . "' WHERE id=$id ;";
		$mysql = $dbh->prepare($SQL);
		$mysql->execute();
	}

	if($self->{primers} eq "yes"){
		$SQL = "UPDATE bioproof SET primers='" . $self->{primer3} . ":" . $self->{primer5} . "' WHERE id=$id ;";
		$mysql = $dbh->prepare($SQL);
		$mysql->execute();
	}

	if($self->{codons} eq "yes"){
		$SQL = "UPDATE bioproof SET codonsearch='" . $self->{codontable} . "' WHERE id=$id;";
		$mysql = $dbh->prepare($SQL);
		$mysql->execute();
	}

	$SQL= "update bioproof set task='RUN' where id=$id;";
	$mysql = $dbh->prepare($SQL);
	$mysql->execute();
	$dbh->disconnect();	

	return $id;

}

sub GetFromDB{
	my ($self) = @_;
	
	my $dbh = DBI->connect("dbi:mysql:database=seqs_southwick;host=psoda2.cs.byu.edu","phylo","") or die("Couldn't connect");
	my $SQL= "update bioproof set PID =".$$." where PID is null and task!='PENDING' limit 1;";
	
	my $Select = $dbh->prepare($SQL);
	$Select->execute();

	$SQL= "select * from bioproof where PID = ".$$.";";
	$Select = $dbh->prepare($SQL);
	$Select->execute();


	if($Select->rows < 1){
		return 0;
	}

	while(my $Row = $Select->fetchrow_hashref){
		$self->{id}= $Row->{id};
		$self->{keywords} = $Row->{keywords};
		$self->{title} = $Row->{name};
		$self->{email} = $Row->{email};

		if($self->{keywords} ne ""){
			$self->{verify} = "yes";
		}
		if($Row->{primers} ne ""){
			$self->{primers} = "yes";
			my @primers = split /:/,$Row->{primers};
			$self->{primer3} = $primers[0];
			$self->{primer5} = $primers[1];
		}
		if($Row->{codonsearch} > 0){
			$self->{codons} = "yes";
			$self->{codontable} = $Row->{codonsearch};
		}	
	}

	return 1;
}

sub GetID {
	my $self = shift;
	return $self->{id};
}

sub PrintInfo {
	my $self = shift;
	my $r = "";

	if($self->{verify} eq "yes"){
		$r .= "looking for keywords: " . $self->{keywords} . "\n";
	}

	if($self->{primers} eq "yes"){
		$r .= "looking for primers: \n\t3': " . $self->{primer3} ."\n\t5': " . $self->{primer5} . "\n";
	}
	if($self->{codons} eq "yes"){
		$r .= "looking for codons\n";
	}
	
	return $r;
}

sub GetFile {
	my $self = shift;
	return "tmp/job_" . $self->{id} . "/file.fas";
}

sub GetKeywords {
	my $self = shift;
	return $self->{keywords};
}

sub GetDir {
	my $self = shift;
	return "tmp/job_" . $self->{id};
}

sub ToVerify {
	my $self = shift;
	return 1 if($self->{verify} eq "yes");
	return 0;
}

sub ToCheckCodons {
	my $self = shift;
	return 1 if($self->{codons} eq "yes");
	return 0;
}

sub Remove {
	my $self = shift;
	
	my $dbh = DBI->connect("dbi:mysql:database=seqs_southwick;host=psoda2.cs.byu.edu","phylo","") or die("error connecting to database");
    	my $SQL= "delete from bioproof where id = ".$self->{id}.";";
	my $Select = $dbh->prepare($SQL);
	$Select->execute();
}


1;
